I am a Graduate Research Assistant of Development and Immsersive Reality Lab(DAIR).

  • I help Professor Jakki Bailey with her research project on the influence of Virtual reality to children.
  • I build 3D model in 3ds Max and develop the VR environment in Unity.
    I am an animator and developer.
  • I am a guest lecturer of Virtual Environment class to teach Unity billboarding script.
  • I Conduct a side research project on people's attitudes towards their own avatars using FaceGen.
  • And I just help with organizing and hosting the open house for our Lab!
  • In the future, I will be a Teaching Assistant of Virtual Environments course to teach Unity!
  • According to data privacy, I only list some of my lab works below.

    We scale the size of the character to test children's reaction towards these changes.

    Model and Animation

    There are some models and animations that I build from scratch for the unity envrionment.

    Billboarding script for all prefabs

    
    			using System.Collections;
    			using System.Collections.Generic;
    			using UnityEngine;
    
    			public class CameraFacingBillboard : MonoBehaviour
    			{
    				private Camera m_Camera;
    
    				private void Start()
    				{
    					m_Camera = GameObject.Find("CenterEyeAnchor").GetComponent();
    				}
    				
    				void LateUpdate()
    				{
    					Vector3 v = m_Camera.transform.position - transform.position;
    					v.x = v.z = 0.0f;
    					transform.LookAt(m_Camera.transform.position - v);
    					// transform.LookAt(transform.position - m_Camera.transform.rotation * Vector3.forward, m_Camera.transform.rotation * Vector3.up);
    
    				}
    			}
    		

    Script for game play

    
    			using System.Collections;
    			using System.Collections.Generic;
    			using UnityEngine;
    			using System.IO;
    			using System;
    			using UnityEngine.UI;
    			
    			public class myPlayerController : MonoBehaviour
    			{
    				public GameObject camera;
    				private float x, y, z;
    				private float yaw, pitch, roll;
    				private GameObject b_sphere, y_sphere, r_sphere;
    				public GameObject[] charaArray;
    				public Vector3[] positionArray = new Vector3[3];
    				private Vector3 temp;
    				private Vector3 size;
    				private Vector3 blue, yellow, red;
    				static private Vector3 ballsize;
    				private float percentage;
    				string path;
    				private static string id;
    				private GameObject globalObject;
    				private List newobject = new List();
    				private float speed = 1.5f;
    				static private Boolean hasCharaInScene = false;
    				private int counter = 0;
    				private string condition;
    				private StreamWriter writer;
    				public float heightPara;
    			
    				//public InputField mainInputField;
    			
    			
    				// Start is called before the first frame update
    				void Start()
    				{
    					b_sphere = GameObject.Find("Sphere_blue");
    					y_sphere = GameObject.Find("Sphere_yellow");
    					r_sphere = GameObject.Find("Sphere_red");
    			
    					
    					//Find the global object
    					globalObject = GameObject.Find("globalObject");
    					// Fetch the ID and condition using prefab
    					id = PlayerPrefs.GetString("ID");
    					condition = PlayerPrefs.GetString("condition");
    					Debug.Log("condition:" + condition);
    					Debug.Log("***ID=" + id);
    					path = string.Format(@"C:\Users\tp24269\Desktop\data\{0}.txt", id);
    			
    					//Write to the csv file
    					writer = new StreamWriter(path, true);
    					writer.WriteLine("{0}", condition);
    					for (int j = 0; j < positionArray.Length; j++)
    					{
    						writer.WriteLine("{0} ", charaArray[j]);
    					}
    					blue = b_sphere.transform.position;
    					yellow = y_sphere.transform.position;
    					red = r_sphere.transform.position;
    					writer.WriteLine("{0}, {1} , {2} ", blue, yellow, red);
    				}
    			
    				// Update is called once per frame
    				void Update()
    				{
    					//open a csv file
    					x = camera.transform.position.x;
    					y = camera.transform.position.y;
    					z = camera.transform.position.z;
    					yaw = camera.transform.rotation.z;
    					pitch = camera.transform.rotation.y;
    					roll = camera.transform.rotation.x;
    					//The order for writing into the data file 
    					string timestamp = DateTime.Now.ToString();
    				   
    			
    					//write to csv
    					writer.WriteLine("{0}, {1},  {2}, {3} , {4} , {5} , {6} ", timestamp, x, y, z, yaw, pitch, roll);
    			
    					//close the file
    					//writer.Close();
    			
    			
    					//Debug.Log("YAW = " + yaw);
    			
    					if (condition == "Condition A")
    					{
    						//Debug.Log("***Condition A***");
    						if (Input.GetKeyDown("1")) {
    							charaAppear();
    							percentage = y / heightPara;
    							counter++;
    						}
    						if (Input.GetKeyDown("2")) {
    							newobject.Clear();
    							charaAppear();
    							percentage = y / (heightPara*2);
    							counter++;
    						}
    						if (Input.GetKeyDown("3"))
    						{
    							newobject.Clear();
    							charaAppear();
    							percentage = y / (heightPara/2);
    							counter++;
    						}
    					}
    					else if (condition == "Condition B") {
    						//Debug.Log("***Condition B***");
    						if (Input.GetKeyDown("1"))
    						{
    							charaAppear();
    							percentage = y / heightPara;
    							counter++;
    						}
    						if (Input.GetKeyDown("2"))
    						{
    							newobject.Clear();
    							charaAppear();
    							percentage = y / (heightPara/2);
    							counter++;
    						}
    						if (Input.GetKeyDown("3"))
    						{
    							newobject.Clear();
    							charaAppear();
    							percentage = y / (heightPara*2);
    							counter++;
    						}
    					}
    			
    					if (Input.GetKeyDown("s"))
    					{
    						y = camera.transform.position.y;
    						Debug.Log("y = " + y);
    					}
    			
    					if (hasCharaInScene)
    						grow(percentage);
    			
    					if (Input.GetKeyDown("d"))
    					{
    						hasCharaInScene = false;
    			
    					}
    			
    					if (!hasCharaInScene)
    					{
    						grow(0);
    						
    						if (counter != 0 && newobject[0].transform.localScale.y <= ballsize.y)
    						{
    							b_sphere.gameObject.SetActive(true);
    							y_sphere.gameObject.SetActive(true);
    							r_sphere.gameObject.SetActive(true);
    							
    						}
    						if (counter != 0 && newobject[0].transform.localScale.y == 0)
    						{
    							for (int i = 0; i < positionArray.Length; i++)
    							{
    								Destroy(newobject[i]);
    							}
    						}
    						//newobject.Clear();
    					}
    			
    				}
    			
    				private void charaAppear()
    				{
    					//if (Input.GetKeyDown("space"))
    					//{
    					b_sphere.gameObject.SetActive(false);
    					y_sphere.gameObject.SetActive(false);
    					r_sphere.gameObject.SetActive(false);
    			
    					for (int i = positionArray.Length - 1; i > 0; i--)
    					{
    						int index = UnityEngine.Random.Range(0, i + 1); //random integer index such that 0 <= index <= 1
    																		//switch
    						if (i != index)
    						{
    							temp = positionArray[i];
    							positionArray[i] = positionArray[index];
    							positionArray[index] = temp;
    						}
    					}
    					for (int j = 0; j < positionArray.Length; j++)
    					{
    						newobject.Add(Instantiate(charaArray[j], positionArray[j], charaArray[j].transform.rotation));
    						ballsize = b_sphere.transform.localScale;
    						newobject[j].transform.localScale = ballsize;
    			
    			
    						//size.x = (charaArray[j].transform.localScale.x * percentage);
    						//size.y = (charaArray[j].transform.localScale.y * percentage);
    						//size.z = (charaArray[j].transform.localScale.z * percentage);
    						//newobject[j].transform.localScale = size;
    					}
    					//}
    			
    			
    					hasCharaInScene = true;
    			
    				}
    			
    				private void grow(float percentage)
    				{
    					size = charaArray[0].transform.localScale * percentage;
    			
    			
    					for (int i = 0; i < newobject.Count; i++)
    					{
    						//newobject[i].transform.localScale = Vector3.Lerp(newobject[i].transform.localScale, size, speed * Time.deltaTime);
    						if (i <= 1)
    						{
    							newobject[i].transform.localScale = Vector3.Lerp(newobject[i].transform.localScale, size, speed * Time.deltaTime);
    						} else
    						{
    							newobject[i].transform.localScale = Vector3.Lerp(newobject[i].transform.localScale, size * 1.2f, speed * Time.deltaTime);
    						}
    			
    					}
    			
    					//newobject[0].transform.localScale = Vector3.Lerp(newobject[0].transform.localScale, size, speed * Time.deltaTime);
    					//newobject[1].transform.localScale = Vector3.Lerp(newobject[1].transform.localScale, size, speed * Time.deltaTime);
    					//newobject[2].transform.localScale = Vector3.Lerp(newobject[2].transform.localScale, size * 1.2f, speed * Time.deltaTime);
    			
    				}
    			
    				private void OnDestroy()
    				{
    					writer.Close();
    				}
    			
    			}
    			
    		

    Avatar Side Project

    This is a side project that I conducted using FaceGen to generate avatars and test people's reaction towards their own avatar.

    Trulli
    Step1: upload pictures and generate avatar.
    Trulli
    Step2: modify demographics feature.
    Trulli
    Step3: add model sets.

    contact me

    FaceGen feedback

    1. The photo quality matters. We need to make sure the light is right when taking the photo, otherwise it will change avatar’s skin color. Also we need to make sure no hair covers part of the face. Profile photo could be a good option.

    2. Current Hairstyle options in FaceGen cannot satisfy their needs and some of them look weird.

    3. Gender feature is not that obvious. Some female participants say their model looks like female without hair.

    4. People usually see their reflections in the mirror. The 3D model is a little bit different to their perception, but it’s still acceptable.

    5. Most participants have positive feeling towards their 3D models. Although there are some deficiencies like the nose part is dark from the front view, they still think the models look similar to real person.

    Contact Me


    If you are interested in my works or have any concern, feel free to contact me.
    Send me an email and I will get back to you as soon as possible.

    Email: tpanchloe, at sign, gmail dot com